home *** CD-ROM | disk | FTP | other *** search
- /* +-------------------------------------------------------------------+ */
- /* | Copyright 1992, 1993, David Koblas (koblas@netcom.com) | */
- /* | | */
- /* | Permission to use, copy, modify, and to distribute this software | */
- /* | and its documentation for any purpose is hereby granted without | */
- /* | fee, provided that the above copyright notice appear in all | */
- /* | copies and that both that copyright notice and this permission | */
- /* | notice appear in supporting documentation. There is no | */
- /* | representations about the suitability of this software for | */
- /* | any purpose. this software is provided "as is" without express | */
- /* | or implied warranty. | */
- /* | | */
- /* +-------------------------------------------------------------------+ */
-
- #include <X11/Intrinsic.h>
- #include <X11/StringDefs.h>
- #include <X11/Shell.h>
- #include <X11/Xaw/Box.h>
- #include <X11/Xaw/Form.h>
- #include <X11/Xaw/Command.h>
- #include <X11/Xaw/Toggle.h>
- #include "xpaint.h"
- #include "misc.h"
- #include "Paint.h"
-
- #include "bitmaps/paintA.xbm"
- #include "bitmaps/paintB.xbm"
- #include "bitmaps/paintC.xbm"
- #include "bitmaps/paintD.xbm"
- #include "bitmaps/paintE.xbm"
- #include "bitmaps/paintF.xbm"
- #include "bitmaps/paintG.xbm"
- #include "bitmaps/paintH.xbm"
- #include "bitmaps/paintI.xbm"
- #include "bitmaps/paintJ.xbm"
- #include "bitmaps/paintK.xbm"
- #include "bitmaps/paintL.xbm"
- #include "bitmaps/paintM.xbm"
- #include "bitmaps/paintN.xbm"
- #include "bitmaps/paintO.xbm"
- #include "bitmaps/paintP.xbm"
- #include "bitmaps/paintQ.xbm"
- #include "bitmaps/paintR.xbm"
- #include "bitmaps/paintS.xbm"
- #include "bitmaps/paintT.xbm"
-
- #define BRUSH(name) \
- (char *)CONCAT(name,_bits), CONCAT(name,_width), CONCAT(name,_height)
-
- typedef struct {
- Pixmap pixmap;
- Cursor cursor;
- char *bits;
- int width, height;
- } BrushItem;
-
- static BrushItem brushList[] = {
- { None, None, BRUSH(paintA) },
- { None, None, BRUSH(paintB) },
- { None, None, BRUSH(paintC) },
- { None, None, BRUSH(paintD) },
- { None, None, BRUSH(paintE) },
- { None, None, BRUSH(paintF) },
- { None, None, BRUSH(paintG) },
- { None, None, BRUSH(paintH) },
- { None, None, BRUSH(paintI) },
- { None, None, BRUSH(paintJ) },
- { None, None, BRUSH(paintK) },
- { None, None, BRUSH(paintL) },
- { None, None, BRUSH(paintM) },
- { None, None, BRUSH(paintN) },
- { None, None, BRUSH(paintO) },
- { None, None, BRUSH(paintP) },
- { None, None, BRUSH(paintQ) },
- { None, None, BRUSH(paintR) },
- { None, None, BRUSH(paintS) },
- { None, None, BRUSH(paintT) },
- };
-
- #define default_bits paintA_bits
- #define default_width paintA_width
- #define default_height paintA_height
-
- typedef struct {
- Boolean isErase, useSecond;
- Pixmap pixmap;
- int width, height;
- } LocalInfo;
-
- static BrushItem *currentBrush = NULL;
- static Boolean eraseMode = True;
-
- static void draw(Widget w, OpInfo *info, LocalInfo *l, int x, int y)
- {
- XRectangle undo;
- int sx = x - l->width / 2;
- int sy = y - l->height / 2;
- GC gc;
-
- if (l->isErase)
- gc = info->base_gc;
- else
- gc = l->useSecond ? info->second_gc : info->first_gc;
-
- XSetClipOrigin(XtDisplay(w), gc, sx, sy);
-
- if (l->isErase && eraseMode && info->base != None) {
- XCopyArea(XtDisplay(w), info->base, info->drawable,
- gc, sx, sy, l->width, l->height, sx, sy);
- } else {
- XFillRectangle(XtDisplay(w), info->drawable,
- gc, sx, sy, l->width, l->height);
- }
-
- if (info->surface == opPixmap) {
- XYtoRECT(sx, sy, sx + l->width, sy + l->height, &undo);
-
- UndoGrow(w, sx, sy);
- UndoGrow(w, sx + l->width, sy + l->height);
- PwUpdate(w, &undo, False);
- }
- }
-
- static void press(Widget w, LocalInfo *l, XButtonEvent *event, OpInfo *info)
- {
- /*
- ** Check to make sure all buttons are up, before doing this
- */
- if ((event->state & (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)) != 0)
- return;
-
- if (info->surface == opWindow && info->isFat)
- return;
-
- l->useSecond = event->button == Button2;
- l->width = currentBrush->width;
- l->height = currentBrush->height;
-
- XSetClipMask(XtDisplay(w), info->first_gc, l->pixmap);
- XSetClipMask(XtDisplay(w), info->second_gc, l->pixmap);
- XSetClipMask(XtDisplay(w), info->base_gc, l->pixmap);
-
- UndoStart(w, info);
-
- draw(w, info, l, event->x, event->y);
- }
-
- static void motion(Widget w, LocalInfo *l, XMotionEvent *event, OpInfo *info)
- {
- if (info->surface == opWindow && info->isFat)
- return;
-
- draw(w, info, l, event->x, event->y);
- }
-
- static void release(Widget w, LocalInfo *l, XButtonEvent *event, OpInfo *info)
- {
- int mask;
- /*
- ** Check to make sure all buttons are up, before doing this
- */
- mask = Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask;
- switch (event->button) {
- case Button1: mask ^= Button1Mask; break;
- case Button2: mask ^= Button2Mask; break;
- case Button3: mask ^= Button3Mask; break;
- case Button4: mask ^= Button4Mask; break;
- case Button5: mask ^= Button5Mask; break;
- }
- if ((event->state & mask) != 0)
- return;
-
- XSetClipMask(XtDisplay(w), info->first_gc, None);
- XSetClipMask(XtDisplay(w), info->second_gc, None);
- XSetClipMask(XtDisplay(w), info->base_gc, None);
- }
-
- static void setPixmap(Widget w, void *brushArg)
- {
- BrushItem *brush = (BrushItem *)brushArg;
- LocalInfo *l = (LocalInfo*)GraphicGetData(w);
-
- l->pixmap = brush->pixmap;
- }
-
- static void setCursor(Widget w, void *brushArg)
- {
- static Boolean inited = False;
- static XColor xcols[2];
- BrushItem *brush = (BrushItem *)brushArg;
- Display *dpy = XtDisplay(w);
-
- if (!inited) {
- Colormap map;
- Screen *screen = XtScreen(w);
-
- inited = True;
- xcols[0].pixel = WhitePixelOfScreen(screen);
- xcols[1].pixel = BlackPixelOfScreen(screen);
-
- XtVaGetValues(w, XtNcolormap, &map, NULL);
-
- XQueryColors(dpy, map, xcols, XtNumber(xcols));
- }
- if (brush->cursor == None) {
- Pixmap mask;
- XImage *src, *msk;
- GC gc;
- Boolean flg;
- int x, y;
-
- src = XGetImage(dpy, brush->pixmap, 0, 0, brush->width,
- brush->height, AllPlanes, ZPixmap);
- msk = NewXImage(dpy, NULL, 1, brush->width, brush->height);
- for (y = 0; y < brush->height; y++) {
- for (x = 0; x < brush->width; x++) {
- Pixel p = XGetPixel(src, x, y);
-
- flg = (Boolean)p;
-
- if (!flg && x > 0)
- flg = XGetPixel(src, x - 1, y);
- if (!flg && x < brush->width - 1)
- flg = XGetPixel(src, x + 1, y);
- if (!flg && y > 0)
- flg = XGetPixel(src, x, y - 1);
- if (!flg && y < brush->height - 1)
- flg = XGetPixel(src, x, y + 1);
-
- XPutPixel(msk, x, y, flg);
- }
- }
- mask = XCreatePixmap(dpy, brush->pixmap, brush->width, brush->height, 1);
- gc = XCreateGC(dpy, mask, 0, 0);
- XPutImage(dpy, mask, gc, msk, 0, 0, 0, 0, brush->width, brush->height);
- XDestroyImage(src);
- XDestroyImage(msk);
- XFreeGC(dpy, gc);
-
- brush->cursor = XCreatePixmapCursor(dpy, brush->pixmap, mask,
- &xcols[1], &xcols[0],
- brush->width / 2, brush->height / 2);
- XFreePixmap(dpy, mask);
- }
- XtVaSetValues(w, XtNcursor, brush->cursor, NULL);
- }
-
- /*
- ** Those public functions
- */
- Boolean EraseGetMode()
- {
- return eraseMode;
- }
- void EraseSetMode(Boolean mode)
- {
- eraseMode = mode;
- }
- void *BrushAdd(Widget w)
- {
- LocalInfo *l = XtNew(LocalInfo);
-
- XtVaSetValues(w, XtNcompress, False, NULL);
-
- l->isErase = False;
- l->pixmap = currentBrush->pixmap;
-
- OpAddEventHandler(w, opWindow|opPixmap, ButtonPressMask,
- FALSE, (OpEventProc)press, (XtPointer)l);
- OpAddEventHandler(w, opWindow|opPixmap, ButtonMotionMask,
- FALSE, (OpEventProc)motion, (XtPointer)l);
- OpAddEventHandler(w, opWindow|opPixmap, ButtonReleaseMask,
- FALSE, (OpEventProc)release, (XtPointer)l);
-
- setCursor(w, (void*)currentBrush);
-
- return l;
- }
- void BrushRemove(Widget w, LocalInfo *l)
- {
- OpRemoveEventHandler(w, opWindow|opPixmap, ButtonPressMask,
- FALSE, (OpEventProc)press, (XtPointer)l);
- OpRemoveEventHandler(w, opWindow|opPixmap, ButtonMotionMask,
- FALSE, (OpEventProc)motion, (XtPointer)l);
- OpRemoveEventHandler(w, opWindow|opPixmap, ButtonReleaseMask,
- FALSE, (OpEventProc)release, (XtPointer)l);
-
- XtFree((XtPointer)l);
- }
- void *EraseAdd(Widget w)
- {
- LocalInfo *l = XtNew(LocalInfo);
-
- XtVaSetValues(w, XtNcompress, False, NULL);
-
- l->isErase = True;
- l->pixmap = currentBrush->pixmap;
-
- OpAddEventHandler(w, opWindow|opPixmap, ButtonPressMask,
- FALSE, (OpEventProc)press, (XtPointer)l);
- OpAddEventHandler(w, opWindow|opPixmap, ButtonMotionMask,
- FALSE, (OpEventProc)motion, (XtPointer)l);
- OpAddEventHandler(w, opWindow|opPixmap, ButtonReleaseMask,
- FALSE, (OpEventProc)release, (XtPointer)l);
-
- setCursor(w, (void*)currentBrush);
-
- return l;
- }
- void EraseRemove(Widget w, LocalInfo *l)
- {
- OpRemoveEventHandler(w, opWindow|opPixmap, ButtonPressMask,
- FALSE, (OpEventProc)press, (XtPointer)l);
- OpRemoveEventHandler(w, opWindow|opPixmap, ButtonMotionMask,
- FALSE, (OpEventProc)motion, (XtPointer)l);
- OpRemoveEventHandler(w, opWindow|opPixmap, ButtonReleaseMask,
- FALSE, (OpEventProc)release, (XtPointer)l);
-
- XtFree((XtPointer)l);
- }
-
- /*
- ** Initializer to create a default brush
- */
-
- void BrushInit(Widget toplevel)
- {
- currentBrush = &brushList[0];
- currentBrush->pixmap = XCreatePixmapFromBitmapData(
- XtDisplay(toplevel),
- RootWindowOfScreen(XtScreen(toplevel)),
- currentBrush->bits,
- currentBrush->width,
- currentBrush->height,
- False, True, 1);
- }
-
- /*
- ** The brush selection dialog
- */
-
- static void closePopup(Widget button, Widget shell)
- {
- XtPopdown(shell);
- }
-
- static void selectBrush(Widget shell, BrushItem *nc)
- {
- currentBrush = nc;
-
- if (((int)CurrentOp[0] == (int)BrushAdd) ||
- ((int)CurrentOp[0] == (int)EraseAdd)) {
- GraphicAll(setCursor, (void*)currentBrush);
- GraphicAll(setPixmap, (void*)currentBrush);
- }
- }
-
- static Widget createDialog(Widget w)
- {
- Widget shell, form, box, icon, firstIcon = 0, close;
- GC gc, igc;
- XGCValues values;
- int i;
- Pixel fg, bg;
- Pixmap pix;
-
- shell = XtVaCreatePopupShell("brush",
- topLevelShellWidgetClass, w,
- NULL);
-
- form = XtVaCreateManagedWidget(NULL,
- formWidgetClass, shell,
- NULL);
-
- box = XtVaCreateManagedWidget("box",
- boxWidgetClass, form,
- NULL);
-
- values.foreground = WhitePixelOfScreen(XtScreen(w));
- values.background = BlackPixelOfScreen(XtScreen(w));
-
- gc = XCreateGC(XtDisplay(w),
- RootWindowOfScreen(XtScreen(w)),
- GCForeground|GCBackground, &values);
-
- values.background = WhitePixelOfScreen(XtScreen(w));
- values.foreground = BlackPixelOfScreen(XtScreen(w));
- igc = XCreateGC(XtDisplay(w),
- RootWindowOfScreen(XtScreen(w)),
- GCForeground|GCBackground, &values);
-
- for (i = 0; i < XtNumber(brushList); i++) {
- if (brushList[i].pixmap == None)
- brushList[i].pixmap = XCreatePixmapFromBitmapData(
- XtDisplay(box),
- RootWindowOfScreen(XtScreen(box)),
- brushList[i].bits,
- brushList[i].width,
- brushList[i].height,
- False, True, 1);
-
- icon = XtVaCreateManagedWidget("icon",
- toggleWidgetClass, box,
- XtNradioGroup, firstIcon,
- NULL);
-
- pix = XCreatePixmap(XtDisplay(box),
- RootWindowOfScreen(XtScreen(box)),
- brushList[i].width,
- brushList[i].height,
- DefaultDepthOfScreen(XtScreen(box)));
-
- XtVaGetValues(icon, XtNforeground, &fg,
- XtNbackground, &bg,
- NULL);
-
- /*
- ** Clear then draw the clipped rectangle in
- */
- XSetClipMask(XtDisplay(w), gc, None);
- XSetForeground(XtDisplay(w), gc, bg);
- XFillRectangle(XtDisplay(w), pix, gc, 0, 0,
- brushList[i].width, brushList[i].height);
- XSetClipMask(XtDisplay(w), gc, brushList[i].pixmap);
- XSetForeground(XtDisplay(w), gc, fg);
- XFillRectangle(XtDisplay(w), pix, gc, 0, 0,
- brushList[i].width, brushList[i].height);
-
- XtVaSetValues(icon, XtNbitmap, pix, NULL);
-
- if (firstIcon == NULL) {
- XtVaSetValues(icon, XtNstate, True, NULL);
- firstIcon = icon;
- }
-
- XtAddCallback(icon, XtNcallback,
- (XtCallbackProc)selectBrush, (XtPointer)&brushList[i]);
- }
-
- close = XtVaCreateManagedWidget("close",
- commandWidgetClass, form,
- XtNfromVert, box,
- XtNtop, XtChainBottom,
- NULL);
-
- XtAddCallback(close, XtNcallback, (XtCallbackProc)closePopup, (XtPointer)shell);
-
- XFreeGC(XtDisplay(w), gc);
- XFreeGC(XtDisplay(w), igc);
-
- AddDestroyCallback(shell, (void (*)(Widget, void *, XEvent *))closePopup, shell);
-
- return shell;
- }
-
- void BrushSelect(Widget w)
- {
- static Widget popup = NULL;
-
- if (popup == NULL)
- popup = createDialog(GetToplevel(w));
-
- XtPopup(popup, XtGrabNone);
- XMapRaised(XtDisplay(popup), XtWindow(popup));
- }
-